package com.heima.wemedia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.heima.common.constants.message.WmNewsUpDownConstants;
import com.heima.common.dtos.PageResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.threadlocal.UserThreadLocalUtils;
import com.heima.common.util.BeanHelper;
import com.heima.common.util.JsonUtils;
import com.heima.model.media.dtos.WmNewsDto;
import com.heima.model.media.dtos.WmNewsPageReqDto;
import com.heima.model.media.dtos.WmNewsResultDTO;
import com.heima.wemedia.entity.WmMaterial;
import com.heima.wemedia.entity.WmNews;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.WmMaterialService;
import com.heima.wemedia.service.WmNewsAuditService;
import com.heima.wemedia.service.WmNewsMaterialService;
import com.heima.wemedia.service.WmNewsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import javafx.scene.paint.Material;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.heima.common.constants.message.WmNewsUpDownConstants.WM_NEWS_UP_OR_DOWN_TOPIC;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author HM
 * @since 2022-09-15
 */
@Slf4j
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Override
    public PageResult<WmNewsResultDTO> findByPage(WmNewsPageReqDto dto) {
//        获取登录用户
        Integer userId = UserThreadLocalUtils.getUserId();
//        构造分页
        Page<WmNews> ipage = new Page<>(dto.getPage(), dto.getSize());
//        构造条件
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.
                eq(WmNews::getWmUserId,userId).
                eq(dto.getChannelId() != null,WmNews::getChannelId ,dto.getChannelId()).
                like(StringUtils.isNotBlank(dto.getKeyword()),WmNews::getTitle,dto.getKeyword()).
                gt(dto.getBeginPubDate()!= null ,WmNews::getPublishTime,dto.getBeginPubDate()).
                lt(dto.getEndPubDate() != null,WmNews::getPublishTime,dto.getEndPubDate());
        if(dto.getStatus() != null && dto.getStatus() != -1){
            if(dto.getStatus() ==1){
//                待审核，对应数据库的 1,3  where status in (1,3)
                queryWrapper.in(WmNews::getStatus,1,3);
            }
            else if(dto.getStatus() ==4){
//                审核通过，对应数据库的 4,8,9 where status in (4,8,9)
                queryWrapper.in(WmNews::getStatus,4,8,9);
            }else{
                queryWrapper.eq(WmNews::getStatus,dto.getStatus());
            }
        }
//        分页查询
        Page<WmNews> wmNewsPage = page(ipage, queryWrapper);
        if(CollectionUtils.isEmpty(wmNewsPage.getRecords())){
            log.info("没有查询到文章数据");
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
//        构造返回
        return new PageResult<>(dto.getPage(),dto.getSize(),wmNewsPage.getTotal(),
                BeanHelper.copyWithCollection(wmNewsPage.getRecords(),WmNewsResultDTO.class));
    }

    @Autowired
    private WmNewsMaterialService newsMaterialService;
    @Autowired
    private WmMaterialService materialService;
    @Autowired
    private WmNewsAuditService wmNewsAuditService;

    /**
     * 新增，修改，提交
     * 保存文章，素材文章中间表
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(WmNewsDto dto) {
//        用户id
        Integer userId = UserThreadLocalUtils.getUserId();
//        对象转换
        WmNews wmNews = BeanHelper.copyProperties(dto, WmNews.class);
        if(dto.getId() == null){
//            新增
            wmNews.setCreatedTime(new Date());
            wmNews.setWmUserId(userId);
        }
        if(!dto.getDraft()){
//            提交操作
            wmNews.setSubmitedTime(new Date());
        }
        if(!CollectionUtils.isEmpty(dto.getImages())){
//            有封面
//            String imageStr = "";
//            for (String url : dto.getImages()) {
//                if(imageStr.length()>0){
//                    imageStr +=",";
//                }
//                imageStr += url;
//            }
            String imageStr = dto.getImages().stream().collect(Collectors.joining(","));
            wmNews.setImages(imageStr);
        }
//       新增后修改自媒体文章
        boolean b = saveOrUpdate(wmNews);
        if(!b){
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
//        获取自媒体文章id
        Integer wmNewsId = wmNews.getId();
//        如果是修改文章，先根据wmNewsId删除中间表数据
        if(dto.getId() != null){
//            修改操作，先根据wmNewsId删除中间表数据
//            delete from wm_news_material where  news_id=?
            newsMaterialService.deleteByNewsId(wmNewsId);
        }
//        解析content，获取内容中的图片id
        if(StringUtils.isNotBlank(wmNews.getContent())){
//            把content的json字符串转java对象
            List<Map<String,Object>> list = JsonUtils.nativeRead(wmNews.getContent(),
                    new TypeReference<List<Map<String, Object>>>() {});
//            从内容中获取素材id集合
            List<Integer> ids = getMaterialIdsByContent(list);
//        保存文章素材中间表
            newsMaterialService.saveNewsAndMaterial(wmNewsId,ids,0);
        }
//        如果有封面，需要用封面的url，获取对应的图片id
        if(!CollectionUtils.isEmpty(dto.getImages())){
//            select * from material where url in (1,2,3)
//            从封面获取素材id集合
            List<Integer> ids = getMaterialIdsByImages(dto.getImages());
            //        保存文章素材中间表
            newsMaterialService.saveNewsAndMaterial(wmNewsId,ids,1);
        }

//       判断是否提交，如果不是提交 直接结束
        if(!dto.getDraft()){
//            如果是提交审核，异步 调用审核的代码
            log.info("异步提交，审核文章");
            wmNewsAuditService.auditWmNews(wmNews);
        }
    }

    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    @Override
    public void downOrUp(WmNewsDto dto) {
//        获取用户的登录信息
        Integer userId = UserThreadLocalUtils.getUserId();
//        获取自媒体文章id
        Integer wmNewsId = dto.getId();
//        获取文章数据
        WmNews wmNews1 = getById(wmNewsId);
        if(wmNews1.getWmUserId().intValue() != userId.intValue()){
            log.error("没有权限操作文章上下架");
            throw new LeadException(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        if(wmNews1.getStatus() != 9){
            log.error("文章状态不是发布");
            throw new LeadException(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        Long articleId = wmNews1.getArticleId();
        if(articleId == null){
            log.error("没有articleid，无法执行上下架");
            throw new LeadException(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        WmNews wmNews = new WmNews();
        wmNews.setId(dto.getId());
        wmNews.setEnable(dto.getEnable());
//        修改自媒体上下架
        boolean b = updateById(wmNews);

//        key - articleId  key-enable  value 1-上架  0- 下架
        Map<String,Long> map = new HashMap<>();
        map.put("articleId",articleId);
        map.put("enable",dto.getEnable()?1L:0L);
        String msg = JsonUtils.toString(map);
//        发送消息
        kafkaTemplate.send(WM_NEWS_UP_OR_DOWN_TOPIC,msg);
    }

    /**
     * 从封面获取素材id集合
     * @param images
     * @return
     */
    private List<Integer> getMaterialIdsByImages(List<String> images) {
        if(CollectionUtils.isEmpty(images)){
            return null;
        }
//        select * from material where url in (1,2,3)
        LambdaQueryWrapper<WmMaterial> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(WmMaterial::getUrl,images);
        List<WmMaterial> wmMaterialList = materialService.list(queryWrapper);
        List<Integer> ids = wmMaterialList.stream().map(WmMaterial::getId).collect(Collectors.toList());
        return ids;
    }

    /**
     * 从内容中获取素材的id集合
     * @param list
     * @return
     */
    private List<Integer> getMaterialIdsByContent(List<Map<String, Object>> list) {

        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        List<Integer> ids = new ArrayList<>();
        for (Map<String, Object> map : list) {
            String type = map.get("type").toString();
            if("image".equals(type)){
                Integer id = Integer.valueOf(map.get("id").toString());
                ids.add(id);
            }
        }
        return ids;
    }
}
